home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / misc / unix / tracker_4_3.lzh / tracker / Amiga / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-13  |  14.8 KB  |  567 lines

  1. /* amiga/main.c 
  2.     vi:se ts=3 sw=3:
  3.  */
  4.  
  5. /* plays sound/noisetracker files on Sparc, silicon graphics.
  6.  * Authors  : Liam Corner - zenith@dcs.warwick.ac.uk
  7.  *            Marc Espie - espie@ens.fr
  8.  *            Steve Haehnichen - shaehnic@ucsd.edu
  9.  *            Andrew Leahy - alf@st.nepean.uws.edu.au
  10.  *
  11.  * Usage    : tracker <filename> 
  12.  *  this version plays compressed files as well.
  13.  *    Modified version of the standard main.c
  14.  */
  15.  
  16. /* $Id: main.c,v 1.9 1994/01/09 23:25:16 Espie Exp espie $
  17.  * $Log: main.c,v $
  18.  * Revision 1.9  1994/01/09  23:25:16  Espie
  19.  * Last bug fix.
  20.  *
  21.  * Revision 1.8  1994/01/09  17:38:28  Espie
  22.  * Generalized open.c.
  23.  *
  24.  * Revision 1.7  1994/01/09  04:49:18  Espie
  25.  * File requester !
  26.  *
  27.  * Revision 1.6  1994/01/08  19:45:29  Espie
  28.  * Uncentralized event handling using event management functions.
  29.  *
  30.  * Revision 1.5  1994/01/08  04:07:20  Espie
  31.  * Yet another mindless bug
  32.  *
  33.  * Revision 1.4  1994/01/08  04:00:52  Espie
  34.  * Suppressed calls to run_in_fg().
  35.  * Added check for / in song names to display something sensible
  36.  * in the title bar...
  37.  *
  38.  * Revision 1.3  1994/01/07  15:57:20  Espie
  39.  * Corrected minor previous song bug.
  40.  *
  41.  * Revision 1.2  1994/01/07  15:08:54  Espie
  42.  * Suppressed spurious code.
  43.  * Added CUT/ADD keywords.
  44.  *
  45.  * Revision 1.1  1994/01/06  22:37:26  Espie
  46.  * Initial revision
  47.  *
  48.  * Revision 1.6  1994/01/05  16:10:49  Espie
  49.  * *** empty log message ***
  50.  *
  51.  * Revision 1.5  1994/01/05  14:54:09  Espie
  52.  * *** empty log message ***
  53.  *
  54.  * Revision 1.4  1994/01/05  13:50:43  Espie
  55.  * Cosmetic change.
  56.  *
  57.  * Revision 1.3  1993/12/28  13:54:44  Espie
  58.  * Use info facility instead of printf for usage message.
  59.  *
  60.  * Revision 1.2  1993/12/26  18:54:21  Espie
  61.  * Modified in a more consistent way.
  62.  *
  63.  * Revision 1.1  1993/12/26  00:55:53  Espie
  64.  * Initial revision
  65.  *
  66.  * Revision 3.20  1993/12/04  17:15:18  espie
  67.  * New version.
  68.  *
  69.  * Revision 3.19  1993/12/04  16:12:50  espie
  70.  * Options changes.
  71.  *
  72.  * Revision 3.18  1993/12/02  15:45:33  espie
  73.  * Changed extended file semantics.
  74.  *
  75.  * Revision 3.17  1993/11/17  15:31:16  espie
  76.  * New version.
  77.  *
  78.  * Revision 3.16  1993/11/11  20:00:03  espie
  79.  * Amiga support.
  80.  *
  81.  * Revision 3.15  1993/08/04  11:55:21  espie
  82.  * Fixed upo previous song bug.
  83.  *
  84.  * Revision 3.13  1993/07/18  10:39:44  espie
  85.  * Added forking under unix. Experimental...
  86.  *
  87.  * Revision 3.11  1993/05/09  14:06:03  espie
  88.  * Fixed up bug with mix option no longer working.
  89.  *
  90.  * Revision 3.10  1993/04/25  15:13:36  espie
  91.  * Force new version.
  92.  *
  93.  * Revision 3.9  1993/01/15  14:00:28  espie
  94.  * Added bg/fg test.
  95.  *
  96.  * Revision 3.7  1992/12/03  15:00:50  espie
  97.  * restore stty.
  98.  *
  99.  * Revision 3.5  1992/11/24  10:51:19  espie
  100.  * Added loads of new options.
  101.  *
  102.  * Revision 3.3  1992/11/22  17:20:01  espie
  103.  * Augmented usage.
  104.  *
  105.  * Revision 3.2  1992/11/20  14:53:32  espie
  106.  * Added finetune.
  107.  *
  108.  * Revision 3.1  1992/11/19  20:44:47  espie
  109.  * Protracker commands.
  110.  *
  111.  * Revision 3.0  1992/11/18  16:08:05  espie
  112.  * New release.
  113.  *
  114.  * Revision 2.20  1992/11/17  17:06:25  espie
  115.  * Added PREVIOUS_SONG handling ???
  116.  * Use streamio for new interface (obsolescent signal handlers), and
  117.  * related changes.
  118.  * Cleaned up path reader, and better signal handling.
  119.  * Support for open_file.
  120.  * Added imask.
  121.  * Use transparent decompression/path lookup through open_file/close_file.
  122.  * Added setup_audio().
  123.  * Added some frequency/oversample/stereo change on the fly.
  124.  * Necessitates rightful closing/reopening of audio.
  125.  * Added compression methods. Changed getopt.
  126.  * Separated mix/stereo stuff.
  127.  * Added transpose feature.
  128.  * Added possibility to get back to MONO for the sgi.
  129.  * Added stereo capabilities to the indigo version.
  130.  * Added recovery and reread for automatic recognition
  131.  * of old/new tracker files.
  132.  * Added two level of fault tolerancy.
  133.  * Added more rational options.
  134.  * Moved almost everything to audio and automaton.
  135.  * Structured part of the code, especially replay ``automaton''
  136.  * and setting up of effects.
  137.  *
  138.  * Revision 1.26  1991/11/17  17:09:53  espie
  139.  * Added missing prototypes.
  140.  * Some more info while loading files.
  141.  * Added FAULT env variable, FAULT resistant playing,
  142.  * for playing modules which are not quite correct.
  143.  * Serious bug: dochangespeed was not reset all the time.
  144.  * Check all these parameters, they MUST be reset for
  145.  * each new song.
  146.  * Fixed a stupid bug: when env variable LOOPING was
  147.  * undefined, we got a segv on strcmp.
  148.  * Now we just test for its existence, since this is
  149.  * about all we want...
  150.  * Bug correction: when doing arpeggio, there might not
  151.  * be a new note, so we have to save the old note value
  152.  * and do the arppeggio on that note.
  153.  * Completely added control with OVERSAMPLE and FREQUENCY.
  154.  * Added control flow.
  155.  * Added pipe decompression, so that now you can do
  156.  * str32 file.Z directly.
  157.  * stdin may go away.
  158.  * Added arpeggio.
  159.  * Added vibslide and portaslide.
  160.  * Added speed command.
  161.  * Added signal control.
  162.  * Error checking: there shouldn't be that many
  163.  * segv signals any more.
  164.  * Moved every command to commands.c.
  165.  * Added some debug code for showing the full
  166.  * sequence for a file.
  167.  * Corrected the bug in volume slide: there is
  168.  * no default value, i.e., if it is 0, it is 0,
  169.  * as stupid as it may seem.
  170.  * Added vibrato.
  171.  * Added fastskip/corrected skip.
  172.  * Modified control flow of the player till
  173.  * it looks like something reasonable (i.e.,
  174.  * the structure is more natural and reflects
  175.  * the way stuff is played actually...)
  176.  * Do not restart the sound when we change instruments
  177.  * on the fly. A bit strange, but it works that way.
  178.  * Modified main to use new data structures.
  179.  * The sound player is MUCH cleaner, it uses now
  180.  * a 3-state automaton for each voice.
  181.  * Corrected ruckus with data type of sample.
  182.  */
  183.      
  184.  
  185. #include <exec/types.h>
  186. #include <exec/memory.h>
  187. #include <proto/dos.h>
  188. #include <proto/exec.h>
  189. #include <dos/dosasl.h>
  190. #include <dos/dosextens.h>
  191. #include <exec/libraries.h>
  192.      
  193. #include "defs.h"
  194.  
  195. #include <stdio.h>
  196. #include <signal.h>
  197. #include <stdlib.h>
  198. #include <string.h>
  199. #ifdef MALLOC_NOT_IN_STDLIB
  200. #include <malloc.h>
  201. #endif
  202.  
  203. #include "song.h"
  204. #include "extern.h"
  205.  
  206. #include "tags.h"
  207. #include "prefs.h"
  208. #include "amiga/amiga.h"
  209.      
  210. ID("$Id: main.c,v 1.9 1994/01/09 23:25:16 Espie Exp espie $")
  211.  
  212. LOCAL struct MinList temp;
  213.  
  214. LOCAL void print_usage()
  215.    {
  216.    GENERIC handle;
  217.    
  218.    handle = begin_info("Usage");
  219.    info(handle, "Usage: tracker files OPTIONS");
  220.    info(handle, "HELP               Display usage information");
  221.    info(handle, "QUIET              Print no output other than errors");
  222.    info(handle, "PICKY              Do not tolerate any faults (default is to ignore most)");
  223.    info(handle, "TOLERANT           Ignore all faults");
  224.    info(handle, "VERBOSE            Show text representation of song");
  225.    info(handle, "REPEATS count      Number of repeats (0 is forever) (default 1)");
  226.    info(handle, "SPEED speed        Song speed.  Some songs want 60 (default 50)");
  227.    info(handle, "NEW/OLD/BOTH       Select default reading type (default is -both)");
  228.    info(handle, "TRANSPOSE n        Transpose notes up by n halftones");
  229.    info(handle, "SCROLL             Show notes scrolling by");
  230.    info(handle, "CUT ab1            Play all instruments except number 1 a and b");
  231.    info(handle, "ADD ab1            Play only instruments except number 1 a and b");
  232.    info(handle, "GUI                open GUI directly");
  233.    end_info(handle);
  234.    }
  235.  
  236. /* arg parser for command-line options. */
  237.  
  238. LOCAL char *template = 
  239. "FILES/M,HELP/S,QUIET/S,TOLERANT/S,PICKY/S,NEW/S,OLD/S,BOTH/S,V=VERBOSE/S,\
  240. TRANS=TRANSPOSE/K/N,R=REPEATS/K,SPEED/K/N,START/K,\
  241. CUT/K,ADD/K,SCROLL/S,GUI/S";
  242.  
  243. #define OPT_HELP 1
  244. #define OPT_QUIET 2
  245. #define OPT_TOLERANT 3
  246. #define OPT_PICKY 4
  247. #define OPT_NEW 5
  248. #define OPT_OLD 6
  249. #define OPT_BOTH 7
  250. #define OPT_VERBOSE 8
  251. #define OPT_TRANSPOSE 9
  252. #define OPT_REPEATS 10
  253. #define OPT_SPEED 11
  254. #define OPT_START 12
  255. #define OPT_CUT 13
  256. #define OPT_ADD 14
  257. #define OPT_SHOW 15
  258. #define OPT_GUI 16
  259.  
  260. LOCAL LONG args[18];
  261.  
  262. LOCAL struct RDArgs *rdargs = 0;
  263.  
  264. LOCAL void free_args()
  265.    {
  266.    if (rdargs)
  267.       FreeArgs(rdargs);
  268.    }
  269.  
  270. /* global variable to catch various types of errors
  271.  * and achieve the desired flow of control
  272.  */
  273. int error;
  274.  
  275. LOCAL struct song *do_read_song(name, type)
  276. char *name;
  277. int type;
  278.    {
  279.    struct song *song;
  280.    struct exfile *file;
  281.  
  282.    file = open_file(name, "r", getenv("MODPATH"));
  283.    if (!file)
  284.       return NULL;
  285.    song = read_song(file, type); 
  286.    close_file(file);
  287.    return song;
  288.    }
  289.  
  290. LOCAL int start;
  291. LOCAL int transpose;
  292.  
  293.  
  294. LOCAL void use_options()
  295.    {
  296.    char *s;
  297.    
  298.    if ((s = args[OPT_CUT]) || (s = args[OPT_ADD]))
  299.       {
  300.       char c;
  301.       ULONG imask = 0;
  302.       
  303.       while (c = *s++)
  304.          {
  305.          if (c >= '1' && c <= '9')
  306.             imask |= 1<< (c-'1');
  307.          else if (c >= 'A' && c <= 'Z')
  308.             imask |= 1 << (c-'A'+9);
  309.          else if (c >= 'a' && c <= 'z')
  310.             imask |= 1 << (c-'a'+9);
  311.          }
  312.       if (args[OPT_CUT])
  313.          set_pref_scalar(PREF_IMASK, imask);
  314.       else
  315.          set_pref_scalar(PREF_IMASK, ~imask);
  316.       }        
  317.    if (args[OPT_OLD])
  318.       set_pref_scalar(PREF_TYPE, OLD);
  319.    if (args[OPT_NEW])
  320.       set_pref_scalar(PREF_TYPE, NEW);
  321.    if (args[OPT_SHOW])
  322.       set_pref_scalar(PREF_SHOW, TRUE);
  323.    if (args[OPT_BOTH])
  324.       set_pref_scalar(PREF_TYPE, BOTH);
  325.    if (args[OPT_REPEATS])
  326.       set_pref_scalar(PREF_REPEATS, *((ULONG *)args[OPT_REPEATS]));
  327.    if (args[OPT_SPEED])
  328.       set_pref_scalar(PREF_SPEED, *((ULONG *)args[OPT_SPEED]));
  329.    if (args[OPT_TRANSPOSE])
  330.       transpose = *((LONG *)args[OPT_TRANSPOSE]);
  331.    if (args[OPT_PICKY])
  332.       set_pref_scalar(PREF_TOLERATE, 0);
  333.    else if (args[OPT_TOLERANT])
  334.       set_pref_scalar(PREF_TOLERATE, 0);
  335.    if (args[OPT_START])
  336.       start = *((ULONG *)args[OPT_START]);
  337.    if (args[OPT_HELP])
  338.       {
  339.       print_usage();
  340.       end_all(0);
  341.       }
  342.    if (args[OPT_VERBOSE])
  343.       set_pref_scalar(PREF_DUMP, TRUE);
  344.    }
  345.  
  346. LOCAL struct song *load_song(name)
  347. char *name;
  348.    {
  349.    struct song *song;
  350.    char *buffer;
  351.    int i, j;
  352.    
  353.    i = strlen(name);
  354.    
  355.    for (j = i; j > 0; j--)
  356.       if (name[j] == '/' || name[j] == ':')
  357.          {
  358.          j++;
  359.          break;
  360.          }
  361.    
  362.    buffer = malloc( i - j + 5);
  363.    if (buffer)
  364.       {
  365.       sprintf(buffer, "%s...", name + j);
  366.       status(buffer);
  367.       }
  368.  
  369.    switch(get_pref_scalar(PREF_TYPE))
  370.       {
  371.    case BOTH:
  372.       song = do_read_song(name, NEW);
  373.       if (song)
  374.          break;
  375.       /* FALLTHRU */
  376.    case OLD:
  377.       song = do_read_song(name, OLD);
  378.       break;
  379.       /* this is explicitly flagged as a new module,
  380.        * so we don't need to look for a signature.
  381.        */
  382.    case NEW:
  383.       song = do_read_song(name, NEW_NO_CHECK);
  384.       break;
  385.       }
  386.    if (buffer)
  387.       {
  388.       status(0);
  389.       free(buffer);
  390.       }
  391.    return song;
  392.    }
  393.  
  394.  
  395. #define PATHSIZE 250
  396.  
  397. struct MinList *expand_names(char *pat[])
  398.    {
  399.    int i;
  400.    struct AnchorPath *ap;
  401.    int error;
  402.    int total;
  403.    struct amiganame *new;
  404.    
  405.    NewList(&temp);
  406.    ap = AllocVec(sizeof(struct AnchorPath) + PATHSIZE, MEMF_CLEAR);
  407.    if (!ap)
  408.       end_all(0);
  409.    ap->ap_Strlen = PATHSIZE;
  410.    for (i = 0; pat[i]; i++)
  411.       {
  412.       for (error = MatchFirst(pat[i], ap); !error; error = MatchNext(ap))
  413.          {
  414.          total = strlen(ap->ap_Buf) +1 ;
  415.          if (strcmp(ap->ap_Buf + total -6, ".info") == 0)
  416.             continue;
  417.          new = malloc(sizeof(struct amiganame) + total);
  418.          if (!new)
  419.             continue;
  420.          strcpy(new->s, ap->ap_Buf);
  421.          new->i = TRUE;
  422.             AddTail(&temp, new);
  423.          }
  424.       MatchEnd(ap);
  425.       }
  426.    FreeVec(ap);
  427.    return &temp;
  428.    }
  429.       
  430. /* add test for >=37 */
  431.  
  432. XT struct DosLibrary *DOSBase;      
  433. int main(argc, argv)
  434. int argc;
  435. char **argv;
  436.    {
  437.    struct song *song;
  438.    struct MinList *list;
  439.    struct amiganame *element, *i;
  440.  
  441.    struct tag *result;
  442.  
  443.    if (DOSBase->dl_lib.lib_Version < 37)
  444.       end_all("Need OS >= 2.04");
  445.  
  446.    start = 0;
  447.    set_pref_scalar(PREF_IMASK, 0);
  448.    set_pref_scalar(PREF_BCDVOL, 0);
  449.    set_pref_scalar(PREF_DUMP, FALSE);
  450.    set_pref_scalar(PREF_SHOW, FALSE);
  451.    set_pref_scalar(PREF_SYNC, FALSE);
  452.    set_pref_scalar(PREF_TYPE, BOTH);
  453.    set_pref_scalar(PREF_REPEATS, 1);
  454.    set_pref_scalar(PREF_SPEED, 50);
  455.    set_pref_scalar(PREF_TOLERATE, 1);
  456.  
  457.    if (argc == 1)
  458.       {
  459.       print_usage();
  460.       end_all(0);
  461.       }
  462.  
  463.    transpose = read_env("TRANSPOSE", 0);
  464.  
  465.  
  466.    if (argc > 0)     /* CLI */
  467.       {
  468.       /* check the command name for default reading type */
  469.  
  470.       rdargs = ReadArgs(template, args, 0);
  471.       if (rdargs)
  472.          at_end(free_args);
  473.       else
  474.          end_all(0);
  475.    
  476.       use_options();
  477.    
  478.       list = expand_names(args[0]);
  479.       }
  480.  
  481. again:      
  482.    if (argc == 0 || args[OPT_GUI])
  483.       {
  484.       launch_requester();
  485.       list = 0;
  486.       forever
  487.          {
  488.          result = get_ui();
  489.          while (result = get_tag(result))
  490.             {
  491.             if (result->type == UI_LOAD_SONG)
  492.                {
  493.                i = (struct amiganame *)result->data.pointer;
  494.                if (!i)
  495.                   end_all(0);
  496.                temp.mlh_Tail = 0;
  497.                temp.mlh_Head = i;
  498.                temp.mlh_TailPred = i->n.mln_Pred;
  499.                i->n.mln_Pred->mln_Succ = &(temp.mlh_Tail);
  500.                i->n.mln_Pred = &temp;
  501.                list = &temp;
  502.                break;
  503.                }
  504.             }
  505.          if (list)
  506.             break;
  507.          await_events();
  508.          }
  509.       }
  510.       
  511.    for (element = list->mlh_Head; element->n.mln_Succ; element = element->n.mln_Succ)
  512.       {
  513.       if (!element->i)
  514.          continue;
  515.       song = load_song(element->s);   
  516.       if (song)
  517.          element->i = TRUE;
  518.       else
  519.          {
  520.          char buffer[150];
  521.  
  522.          sprintf(buffer, "%s is not a song", element->s);
  523.          notice(buffer);
  524.          element->i = FALSE;
  525.          continue;
  526.          }
  527. play_on:
  528.       if (get_pref_scalar(PREF_DUMP))
  529.          dump_song(song); 
  530.       transpose_song(song, transpose);
  531.       setup_audio(0, 1, 1);   /* doesn't really matter on the amiga */
  532.       result = play_song(song, start);
  533.       release_song(song);
  534.       while (result = get_tag(result))
  535.          {
  536.          switch (result->type)
  537.             {
  538.          case PLAY_PREVIOUS_SONG:
  539.             for (element = element->n.mln_Pred; element->n.mln_Pred; 
  540.                element = element->n.mln_Pred)
  541.                if (element->i)
  542.                   {
  543.                   song = load_song(element->s);
  544.                   goto play_on;
  545.                   }
  546.             break;
  547.          case PLAY_LOAD_SONG:
  548.                /* splice play load song result into list */
  549.             i = (struct amiganame *)result->data.pointer;
  550.             element->n.mln_Succ->mln_Pred = i->n.mln_Pred;
  551.             i->n.mln_Pred->mln_Succ = element->n.mln_Succ;
  552.             element->n.mln_Succ = i;
  553.             i->n.mln_Pred = element;
  554.          default:
  555.             break;
  556.             }
  557.          result++;
  558.          }
  559.             
  560.       }
  561.    if (argc == 0 || args[OPT_GUI])
  562.       goto again;
  563.    end_all(0);
  564.    /* NOTREACHED */
  565.    }
  566.  
  567.